package com.wmx.thread.waitset;

import org.springframework.boot.autoconfigure.web.ServerProperties;

import javax.servlet.Servlet;
import java.util.Observer;
import java.util.Optional;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.IntStream;

/**********************************
 * @author wmx
 * @date 2019/8/14 14:09
 * @description:
 * @version 1.0
 * 研究线程的等待集 waitset
 *结果：
 * 1：所有对象都有一个等待集，用来存放该对象调用wait方法之后进入block状态线程
 * 2：线程调用notify后，不是马上执行 （取决于是否得到CPU的执行权限）
 * 3：从wait set 中 被唤醒的线程顺序并不是FIFO
 * 4 ：线程唤醒后需要重新获取锁 ， 继续执 行之前的代码 （这与程序计数器有关）
 *
 * jvm  五大内存区域 ：其中方法区和堆是所有线程共享的，栈，本地方法栈和程序虚拟机则为线程私有的。
 ************************************/
public class WaitSet {
    private final static Object LOCK = new Object();

    private static void work(){
        synchronized (LOCK){
            System.out.println("will come begin");
            try {
                LOCK.wait();  //wait 方法会释放锁 ，从新唤醒后 是不是要从新获取锁，
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("leave come end");
    }


    public static void main(String[] args) {

        
       //创建10个线程
        /*IntStream.rangeClosed(1,10).forEach(i->{
            new Thread(String.valueOf(i)){
                @Override
                public void run() {

                    synchronized (LOCK){
                        try {
                            Optional.of(Thread.currentThread().getName()+"=======》》will come to wait set").ifPresent(System.out::println);
                            LOCK.wait();
                            Optional.of(Thread.currentThread().getName()+"=======》》leave come to wait set").ifPresent(System.out::println);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                }
            }.start();
        });*/

      /*  try {
            Thread.sleep(1000); //让线程睡一觉
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/
        //notify :唤醒线程 随机唤醒一个线程 notifyAll：唤醒所有在等待集中的线程
       /* IntStream.rangeClosed(1,10).forEach(i->{
            synchronized (LOCK){
                LOCK.notify();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        });*/



       //测试 重新唤醒 执行位置

        new Thread(){
            @Override
            public void run() {
                work();
            }
        }.start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (LOCK){
            LOCK.notify();
        }



    }
}

